package com.ubxtech.web.aspect;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.ubxtech.core.context.ContextUtil;
import com.ubxtech.core.exception.ErrorCodeCore;
import com.ubxtech.core.exception.RRException;
import com.ubxtech.core.utils.AntPathMatcherUtil;
import com.ubxtech.web.annotation.Permission;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import jakarta.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Set;

/**
 * 接口权限验证
 * @author Victor.Xiao
 * @since 2023-09-04 16:55
*/
@Aspect
@Component
@Slf4j
@ConditionalOnProperty(name="ubxtech.auth.permissionFLag",havingValue = "1")
public class PermissionAspect {

	@Around("@annotation(com.ubxtech.web.annotation.Permission) || @within(com.ubxtech.web.annotation.Permission)")
	public Object around(ProceedingJoinPoint point) throws Throwable {
		Signature signature = point.getSignature();
		MethodSignature methodSignature = (MethodSignature) signature;
		Method method = methodSignature.getMethod();
		Permission permission = method.getAnnotation(Permission.class);
		if (permission == null) {
			permission = method.getDeclaringClass().getDeclaredAnnotation(Permission.class);
		}
		if (permission == null) {
			return point.proceed();
		}
		String permissionStr = permission.url();
		if (StrUtil.isBlank(permissionStr)) {
			ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
			if (attributes == null) {
				throw new RRException(ErrorCodeCore.FORBIDDEN);
			}
			HttpServletRequest request = attributes.getRequest();
			permissionStr = request.getRequestURI();
		}
		if (StrUtil.isBlank(permissionStr)) {
			throw new RRException(ErrorCodeCore.FORBIDDEN);
		}


		if (!hasPerm(permissionStr)) {
			throw new RRException(ErrorCodeCore.FORBIDDEN);
		}
		return point.proceed();
	}

	/**
	 * 验证用户是否具备接口权限
	 * @author Victor.Xiao
	 * @since 2023-09-04 17:00
	 * @param permission url
	 * @return boolean
	*/
	public boolean hasPerm(String permission) {
		Set<String> permissions = ContextUtil.getContextToken().getPermissions();
		if (CollectionUtil.isEmpty(permissions)) {
			return false;
		}
		return AntPathMatcherUtil.match(permission,permissions);

	}


}
